//
// Created by Zsir on 2025/8/22.
//

#include "Acceptor.h"
#include "EventLoop.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <cstring>

Acceptor::Acceptor(EventLoop *loop, const std::string &ip, uint16_t port)
    : loop_(loop),
      acceptFd_(socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)),
      acceptChannel_(loop, acceptFd_),
      listenning_(false)
{

    if (acceptFd_ < 0)
    {
        std::cerr << "Acceptor::Acceptor - 创建套接字失败" << std::endl;
        abort();
    }

    int optval = 1;
    setsockopt(acceptFd_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

    sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    inet_pton(AF_INET, ip.c_str(), &addr.sin_addr);

    if (bind(acceptFd_, (sockaddr *) &addr, sizeof(addr)) < 0)
    {
        std::cerr << "Acceptor::Acceptor - 绑定地址失败" << std::endl;
        abort();
    }

    acceptChannel_.setReadCallback(std::bind(&Acceptor::handleRead, this));
}

Acceptor::~Acceptor()
{
    acceptChannel_.disableAll();
    acceptChannel_.remove();
    close(acceptFd_);
}

void Acceptor::listen()
{
    loop_->assertInLoopThread();
    listenning_ = true;

    if (::listen(acceptFd_, SOMAXCONN) < 0)
    {
        std::cerr << "Acceptor::listen - 监听失败" << std::endl;
        abort();
    }

    acceptChannel_.enableReading();
}

void Acceptor::handleRead()
{
    loop_->assertInLoopThread();
    sockaddr_in peerAddr;
    socklen_t addrLen = sizeof(peerAddr);

    int connfd = accept4(acceptFd_, (sockaddr *) &peerAddr, &addrLen,
                         SOCK_NONBLOCK | SOCK_CLOEXEC);
    if (connfd < 0)
    {
        std::cerr << "Acceptor::handleRead - accept4 失败" << std::endl;
        return;
    }

    if (newConnectionCallback_)
    {
        newConnectionCallback_(connfd, peerAddr);
    } else
    {
        close(connfd);
    }
}
